addonName, ns = ...

local module = {}
module.name = "Unit Frames"
module.Init = function()
    if not SCDB.modules[module.name] then return end
    if SCDB[module.name] == nil then SCDB[module.name] = {} end
    if SCDB[module.name]["3D portaits"] == nil then SCDB[module.name]["3D portaits"] = false end
    if SCDB[module.name]["Class portaits"] == nil then SCDB[module.name]["Class portaits"] = true end
    if SCDB[module.name]["Large aura size"] == nil then SCDB[module.name]["Large aura size"] = 27 end
    if SCDB[module.name]["Small aura size"] == nil then SCDB[module.name]["Small aura size"] = 24 end
    if SCDB[module.name]["Necrotic tracker"] == nil then SCDB[module.name]["Necrotic tracker"] = true end
    if SCDB[module.name]["Custom textures"] == nil then SCDB[module.name]["Custom textures"] = false end
    if SCDB[module.name]["Scale"] == nil then SCDB[module.name]["Scale"] = 1.1 end

    SCDB[module.name].opt = SCDB[module.name].opt or {}
    
    hooksecurefunc(getmetatable(PlayerFrameHealthBar).__index, "Show", function(bar, ...)
        if bar:GetParent().healthbar then
            if bar:GetParent():GetScale()~=SCDB[module.name]["Scale"] then bar:GetParent():SetScale(SCDB[module.name]["Scale"]) end
            if bar.styled == nil then
                if SCDB[module.name]["Custom textures"] == true then
                    bar:SetStatusBarTexture("Interface\\TokenFrame\\UI-TokenFrame-CategoryButton")
                    bar:GetStatusBarTexture():SetDesaturated(1)
                    bar:GetStatusBarTexture():SetTexCoord(0, 1, 0.609375, 0.796875)
                    bar:GetStatusBarTexture():SetHorizTile(true)
                else
                    bar:SetStatusBarTexture("Interface\\Addons\\"..addonName.."\\media\\texture\\statusbar")
                    bar:GetStatusBarTexture():SetHorizTile(true)
                end
                bar.styled = true
            end
        end
    end)
    
    local cc = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[select(2, UnitClass("player"))] or RAID_CLASS_COLORS[select(2, UnitClass("player"))] or  { r=.5, g=.5, b=.5 }
    
    if UIMovableFrames then tinsert(UIMovableFrames, PartyMemberFrame1) end

    local function PaintTextures()
        local cl = (SCDB["Main"].ClassColored == true)
        local r1, g1, b1, a1 = 1,1,1,1 -- top color
        local r2, g2, b2, a2 = cl and cc.r or .4, cl and cc.g or .4, cl and cc.b or .4, 1 -- bottom color
    
        for i,v in pairs({
            -- Action bars
            MainMenuMaxLevelBar0,
            MainMenuMaxLevelBar1,
            MainMenuBarTexture0,
            MainMenuBarTexture1,
            MainMenuBarTexture2,
            MainMenuBarTexture3,
            MainMenuXPBarTextureRightCap,
            MainMenuXPBarTextureMid,
            MainMenuXPBarTextureLeftCap,
            ActionBarUpButton:GetRegions(),
            ActionBarDownButton:GetRegions(),
            BonusActionBarFrame:GetRegions(),
            KeyRingButton:GetRegions(),	
            select(2, BonusActionBarFrame:GetRegions()),
            
            -- Unit frames
            PlayerFrameTexture,
            TargetFrameTextureFrameTexture,
            FocusFrameTextureFrameTexture,
            TargetFrameToTTextureFrameTexture,
            FocusFrameToTTextureFrameTexture,
            PetFrameTexture,
            
            -- Minimap
            MinimapBackdrop,
            MinimapBorder,
            MiniMapMailBorder,
            MiniMapTrackingButtonBorder,
            MinimapBorderTop,
            MinimapZoneTextButton,
            MiniMapWorldMapButton,
            MiniMapWorldMapButton,
            MiniMapWorldIcon,
            MinimapZoomIn:GetRegions(),
            MinimapZoomOut:GetRegions(),
            TimeManagerClockButton:GetRegions(),
            MiniMapWorldMapButton:GetRegions(),
            select(6, GameTimeFrame:GetRegions()),
            
            -- Exp bubble dividers
            MainMenuXPBarDiv1,
            MainMenuXPBarDiv2,
            MainMenuXPBarDiv3,
            MainMenuXPBarDiv4,
            MainMenuXPBarDiv5,
            MainMenuXPBarDiv6,
            MainMenuXPBarDiv7,
            MainMenuXPBarDiv8,
            MainMenuXPBarDiv9,
            MainMenuXPBarDiv10,
            MainMenuXPBarDiv11,
            MainMenuXPBarDiv12,
            MainMenuXPBarDiv13,
            MainMenuXPBarDiv14,
            MainMenuXPBarDiv15,
            MainMenuXPBarDiv16,
            MainMenuXPBarDiv17,
            MainMenuXPBarDiv18,
            MainMenuXPBarDiv19,
            
            -- Chat frame buttons
            select(2, FriendsMicroButton:GetRegions()),
            ChatFrameMenuButton:GetRegions(),
            ChatFrame1ButtonFrameUpButton:GetRegions(),
            ChatFrame1ButtonFrameDownButton:GetRegions(),
            select(2, ChatFrame1ButtonFrameBottomButton:GetRegions()),
            ChatFrame2ButtonFrameUpButton:GetRegions(),
            ChatFrame2ButtonFrameDownButton:GetRegions(),
            select(2, ChatFrame2ButtonFrameBottomButton:GetRegions()),
            
            -- Chat edit box
            select(6, ChatFrame1EditBox:GetRegions()),
            select(7, ChatFrame1EditBox:GetRegions()),
            select(8, ChatFrame1EditBox:GetRegions()),
            select(5, ChatFrame1EditBox:GetRegions()),
            
            -- Micro menu buttons
            select(2, SpellbookMicroButton:GetRegions()),
            select(3, CharacterMicroButton:GetRegions()),
            select(2, TalentMicroButton:GetRegions()),
            select(2, AchievementMicroButton:GetRegions()),
            select(2, QuestLogMicroButton:GetRegions()),
            select(2, GuildMicroButton:GetRegions()),
            select(3, PVPMicroButton:GetRegions()),
            select(2, LFDMicroButton:GetRegions()),
            select(4, MainMenuMicroButton:GetRegions()),
            select(2, HelpMicroButton:GetRegions()),
            
            -- Other
            select(2, CastingBarFrame:GetRegions()),
            select(2, MirrorTimer1:GetRegions()),
            MainMenuBarLeftEndCap,
            MainMenuBarRightEndCap,
        }) do
            if v:GetObjectType() == "Texture" then
                v:SetVertexColor(1, 1, 1)
                v:SetDesaturated(1)
                v:SetVertexColor(r2, g2, b2)
            end
        end
        
        -- Desaturation fix for elite target texture (thanks SDPhantom!)
        hooksecurefunc("TargetFrame_CheckClassification", function(self)
            self.borderTexture:SetDesaturated(1)
        end)
        
        -- Game tooltip
        TOOLTIP_DEFAULT_COLOR = { r = r1 * .6, g = g1 * .6, b = b1 * .6 }
        TOOLTIP_DEFAULT_BACKGROUND_COLOR = { r = r2 * .1, g = g2 * .1, b = b2 * .1}
        
        if SCDB["Main"].ClassColored == true then
            MinimapBackdrop:SetBackdropBorderColor(cc.r*.5, cc.g*.5, cc.b*.5)
        else
            MinimapBackdrop:SetBackdropBorderColor(.4,.4,.4)
        end
    end
    
    local reputationscale = CreateFrame("StatusBar", "reputationscale", PlayerFrame)
    reputationscale:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
    reputationscale:SetStatusBarColor(0, .8, 0)
    reputationscale:RegisterEvent("UPDATE_FACTION")

    
    ---------------------------------------------------
    -- PLAYER
    ---------------------------------------------------
    
    PlayerFrame_ToPlayerArt = function(self)
        PaintTextures()
        
        PlayerFrame:SetScale(1.1)
        TargetFrame:SetScale(1.1)
        
        PlayerFrame.state = "player"
        
        UnitFrame_SetUnit(self, "player", PlayerFrameHealthBar, PlayerFrameManaBar)
        UnitFrame_SetUnit(PetFrame, "pet", PetFrameHealthBar, PetFrameManaBar)
        PetFrame_Update(PetFrame)
        PlayerFrame_Update()
        BuffFrame_Update()
        ComboFrame_Update()
                
        PlayerFrameTexture:Show()
        PlayerFrame_HideVehicleTexture()
        PlayerName:SetPoint("CENTER",50,19)
        PlayerLeaderIcon:SetPoint("TOPLEFT",40,-12)
        PlayerMasterIcon:SetPoint("TOPLEFT",80,-10)
        PlayerFrameGroupIndicator:SetPoint("BOTTOMLEFT", PlayerFrame, "TOPLEFT", 97, -20)
        
        PlayerPVPIcon:SetSize(50,50)
        PlayerPVPIcon:SetPoint("TOPLEFT", 25, -25)
        PlayerName:SetWidth(0.01)
        PlayerFrameGroupIndicatorText:ClearAllPoints()
        PlayerFrameGroupIndicatorText:SetPoint("BOTTOMLEFT", PlayerFrame, "TOP", 0, -20)
        PlayerFrameGroupIndicatorLeft:Hide()
        PlayerFrameGroupIndicatorMiddle:Hide()
        PlayerFrameGroupIndicatorRight:Hide()
        PlayerFrameHealthBar:ClearAllPoints()
        PlayerFrameHealthBar:SetPoint("TOPLEFT", 106, -24)
        PlayerFrameHealthBar:SetSize(119, 18)
        PlayerFrameHealthBarText:ClearAllPoints()
        PlayerFrameHealthBarText:SetPoint("RIGHT", PlayerFrameHealthBar, 0, 0)
        PlayerFrameManaBar:ClearAllPoints()
        PlayerFrameManaBar:SetPoint("TOPLEFT", 106, -43)
        PlayerFrameManaBar:SetSize(119, 10)
        PlayerFrameManaBarText:ClearAllPoints()
        PlayerFrameManaBarText:SetPoint("RIGHT", PlayerFrameManaBar, 0, 0)
        PlayerFrameManaBarText:SetFont(PlayerFrameManaBarText:GetFont(), 9, "OUTLINE")
        
        PlayerHitIndicator:ClearAllPoints()
        PlayerHitIndicator:SetPoint("BOTTOM", PlayerFrame.portrait, "TOP", 0, 17)
        PlayerHitIndicator.SetTextHeight = function(self, fh)
            PlayerFrame.feedbackText:SetFont(self:GetFont(), fh, "OUTLINE")
        end
        PlayerFrame.feedbackFontHeight = 16
        
        PlayerFrameFlash:SetTexture("")
        PlayerFrameFlash.SetTexture = function() end
        
        PlayerFrameAlternateManaBarBorder:Hide()
        PlayerFrameAlternateManaBarBorder.Show = function() end
        PlayerFrameAlternateManaBarBackground:Hide()
        PlayerFrameAlternateManaBarBackground.Show = function() end
        PlayerFrameAlternateManaBar:ClearAllPoints()
        PlayerFrameAlternateManaBar:SetPoint("TOPLEFT", 106, -53)
        PlayerFrameAlternateManaBar:SetHeight(10)
        PlayerFrameAlternateManaBar:SetWidth(PlayerFrameManaBar:GetWidth())
        PlayerFrameAlternateManaBar.SetWidth = function() end
        PlayerFrameAlternateManaBarText:ClearAllPoints()
        PlayerFrameAlternateManaBarText:SetPoint("RIGHT", PlayerFrameAlternateManaBar, 0, 0)
        PlayerFrameAlternateManaBarText:SetFont(PlayerFrameAlternateManaBarText:GetFont(), 8, "OUTLINE")
        PlayerStatusTexture:Hide()
        PlayerStatusTexture.Show = function() end
        
        PlayerFrameBackground:SetWidth(119)
        PlayerLevelText:Show()
        PlayerFrameFlash:SetTexture("Interface\\TargetingFrame\\UI-TargetingFrame-Flash")
        PlayerFrameFlash:SetTexCoord(0.9453125, 0, 0, 0.181640625)
    end
    
    
    local function UpdatePlayerFrame()
        if not UnitHasVehicleUI("player") then
            if not PlayerFrameAlternateManaBar:IsShown() then
                if ReputationWatchBar:IsShown() then
                    reputationscale:Show()
                    reputationscale:SetScript("OnEvent", function()
                        reputationscale:SetMinMaxValues(ReputationWatchStatusBar:GetMinMaxValues())
                        reputationscale:SetValue(ReputationWatchStatusBar:GetValue())
                    end)
                    reputationscale:SetStatusBarColor(ReputationWatchStatusBar:GetStatusBarColor())
                    reputationscale:SetScript("OnEnter", function(self)
                        GameTooltip:ClearLines()
                        GameTooltip:SetOwner(self, ANCHOR_TOPLEFT)
                        GameTooltip:AddLine(ReputationWatchStatusBarText:GetText())
                        GameTooltip:Show()
                    end)
                    reputationscale:SetScript("OnLeave", function(self) GameTooltip:Hide() end)
                else
                    if reputationscale:IsShown() then reputationscale:Hide() end
                end
                reputationscale:ClearAllPoints()
                reputationscale:SetHeight(10)
                reputationscale:SetWidth(PlayerFrameHealthBar:GetWidth())
                reputationscale.SetWidth = function() end
                reputationscale:SetPoint("TOPLEFT", 106, -53)
            else
               if reputationscale:IsShown() then reputationscale:Hide() end
            end

            ---------------------------------------------------
            -- RUNES/TOTEMS/COMBOPOINTS
            ---------------------------------------------------
            local class = select(2, UnitClass("player"))
            
            if class == "SHAMAN" then
                for i = 1, 4 do
                    local totem = _G["TotemFrameTotem"..i]
                    totem:SetSize(30,30)
                    if not totem.bg then
                        select(2, totem:GetChildren()):Hide()
                        select(2, totem:GetChildren()).Show = function() end
                        _G["TotemFrameTotem"..i.."IconTexture"]:SetTexCoord(.1, .9, .1, .9)
                        _G["TotemFrameTotem"..i.."Background"]:Hide()
                        _G["TotemFrameTotem"..i.."Background"].Show = function () end
                        _G["TotemFrameTotem"..i.."Duration"]:Hide()
                        _G["TotemFrameTotem"..i.."Duration"].Show = function() end
                        totem:ClearAllPoints()
                        if i == 1 then
                            totem:SetPoint("LEFT", TotemFrame, "LEFT", 2, 0)
                        else
                            totem:SetPoint("LEFT", _G["TotemFrameTotem"..(i-1)], "RIGHT", 2, 0)
                        end
                        _G["TotemFrameTotem"..i.."Icon"]:SetSize(totem:GetWidth()-4, totem:GetWidth()-4)
                        totem.bg = CreateFrame("Frame", nil, totem)
                        totem.bg:SetFrameLevel(_G["TotemFrameTotem"..i.."Icon"]:GetFrameLevel() + 1)
                        totem.bg:SetSize(totem:GetWidth(), totem:GetWidth())
                        totem.bg:SetPoint("CENTER", totem, "CENTER")
                        totem.bgt = totem.bg:CreateTexture(nil, "ARTWORK")
                        totem.bgt:SetAllPoints(totem.bg)
                        
                        totem.bgt:SetTexture("Interface\\Buttons\\UI-TotemBar")
                        totem.bgt:SetTexCoord(1 / 128, 35 / 128, 207 / 256, 240 / 256)
                        totem.bgt:SetDesaturated(1)
                    end
                end
                
            elseif class == "DEATHKNIGHT" then
                RuneFrame:ClearAllPoints()
                RuneFrame:SetPoint("TOPLEFT", PlayerFrameManaBar, "BOTTOMLEFT", 0, -13)
                for i = 1, 6 do
                    local rune = _G["RuneButtonIndividual"..i]
                    if not rune.bg then
                        rune:SetSize(20, 20)
                        select(1, _G["RuneButtonIndividual"..i.."Border"]:GetRegions()):SetTexture("")
                        _G["RuneButtonIndividual"..i.."Rune"]:SetTexCoord(.3, .7, .3, .7)
                        _G["RuneButtonIndividual"..i.."Cooldown"]:SetSize(rune:GetWidth()-4, rune:GetWidth()-4)
                        _G["RuneButtonIndividual"..i.."Rune"]:SetSize(rune:GetWidth()-4, rune:GetWidth()-4)
                        rune:ClearAllPoints()
                        if i == 1 then
                            rune:SetPoint("LEFT", RuneFrame, "LEFT", 2, 0)
                        else
                            rune:SetPoint("LEFT", _G["RuneButtonIndividual"..(i-1)], "RIGHT", 0, 0)
                        end
                        rune.bg = CreateFrame("Frame", nil, rune)
                        rune.bg:SetFrameLevel(rune:GetFrameLevel() + 1)
                        rune.bg:SetSize(rune:GetWidth(), rune:GetWidth())
                        rune.bg:SetPoint("CENTER")
                        rune.bgt = rune.bg:CreateTexture(nil, "ARTWORK")
                        rune.bgt:SetAllPoints(rune.bg)
                        rune.bgt:SetTexture("Interface\\Buttons\\UI-TotemBar")
                        rune.bgt:SetTexCoord(1 / 128, 35 / 128, 207 / 256, 240 / 256)
                        rune.bgt:SetDesaturated(1)
                    end
                end
            end
        else
            PlayerFrameHealthBar:SetHeight(12)
            PlayerFrameManaBar:SetHeight(12)
        end
    end
    
    hooksecurefunc("ReputationWatchBar_Update", UpdatePlayerFrame)

    
    ---------------------------------------------------
    -- TARGET
    ---------------------------------------------------
    TargetFrame.nameBackground:Hide()
    TargetFrame:SetHitRectInsets(0,0,0,0)
    TargetFrame.deadText:ClearAllPoints()
    TargetFrame.deadText:SetPoint("CENTER", TargetFrameHealthBar, "CENTER", 0, 0)
    TargetFrameTextureFrameName:ClearAllPoints()
    TargetFrameTextureFrameName:SetPoint("BOTTOMRIGHT", TargetFrame, "TOP", 0, -20)
    TargetFrameHealthBar:ClearAllPoints()
    TargetFrameHealthBar:SetPoint("TOPLEFT", 5, -24)
    TargetFrameHealthBar:SetHeight(18)
    TargetFrameTextureFrameHealthBarText:ClearAllPoints()
    TargetFrameTextureFrameHealthBarText:SetPoint("RIGHT", TargetFrameHealthBar, 0, 0)
    TargetFrameManaBar:ClearAllPoints()
    TargetFrameManaBar:SetPoint("TOPLEFT", 5, -43)
    TargetFrameManaBar:SetHeight(10)
    TargetFrameTextureFrameManaBarText:ClearAllPoints()
    TargetFrameTextureFrameManaBarText:SetPoint("RIGHT", TargetFrameManaBar, 0, 0)
    TargetFrameTextureFrameManaBarText:SetFont(TargetFrameTextureFrameManaBarText:GetFont(), 9, "OUTLINE")

    TargetFrame.threatNumericIndicator:SetPoint("BOTTOM", PlayerFrame, "TOP", 75, -22)
    if SCDB[module.name]["Necrotic tracker"] == true then
        TargetFrame.nt = _G["NecroticOverlayFrame"] or CreateFrame("frame", "NecroticOverlayFrame")
        TargetFrame.NecroticOverlay = TargetFrame.healthbar:CreateTexture(nil, "OVERLAY")
        TargetFrame.NecroticOverlay:SetAllPoints(TargetFrame.healthbar)
        TargetFrame.NecroticOverlay:SetTexture(1, 1, 1, 1)
        TargetFrame.NecroticOverlay:SetBlendMode("BLEND")
        TargetFrame.NecroticOverlay:SetVertexColor(0, 0, 0, 0.4)
        TargetFrame.NecroticOverlay:Hide()
        TargetFrame.nt.bar = TargetFrame.healthbar
        
        TargetFrame.nt:RegisterEvent("UNIT_AURA")
        TargetFrame.nt:RegisterEvent("PLAYER_TARGET_CHANGED")
        TargetFrame.nt:RegisterEvent("COMBAT_EVENT_UNFILTERED")
        TargetFrame.nt:SetScript("OnEvent", function(self, ...)
            TargetFrame.NecroticOverlay:Hide()
            local i = 1
            while true do
                local _, _, texture, _, _, _, _, _, _, _, spellId = UnitAura("target", i, "HARMFUL")
                if not texture then break end
                if spellId == 73975 then
                    if not NecroticStrikeTooltip then
                        NecroticStrikeTooltip = CreateFrame("GameTooltip", "NecroticStrikeTooltip", nil, "GameTooltipTemplate")
                        NecroticStrikeTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
                    end
                    NecroticStrikeTooltip:ClearLines()
                    NecroticStrikeTooltip:SetUnitDebuff("target", i)
                    self.NecroAbsorb = tonumber(string.match(_G[NecroticStrikeTooltip:GetName() .. "TextLeft2"]:GetText(), "(%d+%s?) .*"))
                    if self.NecroAbsorb > 0 then
                        local currHealth = self.bar:GetValue()
                        local maxHealth = select(2, self.bar:GetMinMaxValues())
                        local lOfs = (self.bar:GetWidth() * (currHealth / maxHealth)) - (self.bar:GetWidth() * (self.NecroAbsorb / maxHealth))
                        local rOfs = (self.bar:GetWidth() * (currHealth / maxHealth)) - self.bar:GetWidth()
                        if lOfs < 0 then lOfs = 0 end
                        if rOfs > 0 then rOfs = 0 end
                        TargetFrame.NecroticOverlay:ClearAllPoints()
                        TargetFrame.NecroticOverlay:SetPoint("LEFT", lOfs, 0)
                        TargetFrame.NecroticOverlay:SetPoint("RIGHT", rOfs, 0)
                        TargetFrame.NecroticOverlay:SetPoint("TOP", 0, 0)
                        TargetFrame.NecroticOverlay:SetPoint("BOTTOM", 0, 0)
                        local r, g, b = self.bar:GetStatusBarColor()
                        TargetFrame.NecroticOverlay:SetVertexColor(1-r, 1-g, 1-b, 0.4)
                        TargetFrame.NecroticOverlay:Show()
                    else
                        TargetFrame.NecroticOverlay:Hide()
                    end
                end
                i = i + 1
            end
        end)
    end
 
 
    ---------------------------------------------------
    -- FOCUS
    --------------------------------------------------- 
    FocusFrame.nameBackground:Hide()
    FocusFrame.deadText:ClearAllPoints()
    FocusFrame.deadText:SetPoint("CENTER", FocusFrameHealthBar, "CENTER", 0, 0)
    FocusFrameTextureFrameName:ClearAllPoints()
    FocusFrameTextureFrameName:SetPoint("BOTTOMRIGHT", FocusFrame, "TOP", 0, -20)
    FocusFrameHealthBar:ClearAllPoints()
    FocusFrameHealthBar:SetPoint("TOPLEFT", 5, -24)
    FocusFrameHealthBar:SetHeight(18)
    FocusFrameTextureFrameHealthBarText:ClearAllPoints()
    FocusFrameTextureFrameHealthBarText:SetPoint("RIGHT", FocusFrameHealthBar, 0, 0)
    FocusFrameManaBar:ClearAllPoints()
    FocusFrameManaBar:SetPoint("TOPLEFT", 5, -43)
    FocusFrameManaBar:SetHeight(10)
    FocusFrameTextureFrameManaBarText:ClearAllPoints()
    FocusFrameTextureFrameManaBarText:SetPoint("RIGHT", FocusFrameManaBar, 0, 0)
    FocusFrame.threatNumericIndicator:SetWidth(0.01)
    FocusFrame.threatNumericIndicator.bg:Hide()
    FocusFrame.threatNumericIndicator.text:Hide()

    ---------------------------------------------------
    -- CLASS COLOR
    ---------------------------------------------------
    local colour = function(bar, unit)
        if unit and unit == bar.unit then
            local t = { r=0, g=1, b=0 }
            
            if (UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit)) then
                t = { r=.6, g=.6, b=.6}
            elseif (not UnitIsConnected(unit)) then
                t = { r=.6, g=.6, b=.6}
            elseif(UnitIsUnit(unit, "pet")) then
                local happiness = {
                 [1] = {r=1, g=0, b=0}, -- need.... | unhappy
                 [2] = {r=1, g=1, b=0}, -- new..... | content
                 [3] = {r=0, g=1, b=0}, -- colors.. | happy
                }
                t = { r=0, g=1, b=0 }
            elseif UnitIsPlayer(unit) then
                local _, class = UnitClass(unit)
                t = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class] or  { r=0, g=1, b=0 }
            elseif UnitReaction(unit, "player") then
                t = FACTION_BAR_COLORS and FACTION_BAR_COLORS[UnitReaction(unit, "player")] or { r=0, g=1, b=0 }
            else
                t = {r=0, g=1, b=0}
            end
            
            bar:SetStatusBarColor(t.r, t.g, t.b)
        end
    end
    
    hooksecurefunc("UnitFrameHealthBar_Update", colour)
    hooksecurefunc("HealthBar_OnValueChanged", function(self)
       colour(self, self.unit)
    end)

    ---------------------------------------------------
    -- TARGET AURA STYLE & SET POINT
    ---------------------------------------------------
    local setStyleAura = function(bname, index, isDebuff)
        local button = _G[bname..index]
        local icon   = _G[bname..index.."Icon"]
        local cd     = _G[bname..index.."Cooldown"]
        local count  = _G[bname..index.."Count"]
        local border  = _G[bname..index.."Border"]

        if button.bd==nil then
            button.bd = button:CreateTexture(bname..index.."Overlay", "BORDER")
            button.bd:SetAllPoints(button)
            button.bd:SetTexture("Interface\\Buttons\\UI-TotemBar")
            button.bd:SetTexCoord(1 / 128, 35 / 128, 207 / 256, 240 / 256)
            button.bd:SetDesaturated(1)
        end
        
        if border then
            border:Hide()
            button.bd:SetVertexColor(unpack({border:GetVertexColor()}))
            border.Show = function() end
        end
        
        if icon then
            icon:SetTexCoord(.1, .9, .1, .9)
            icon:SetPoint("TOPLEFT", button, "TOPLEFT", 3, -3)
            icon:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -3, 3)
            if cd then
                cd:SetAllPoints(icon)
            end
        end
        
        if count then
            count:SetDrawLayer("OVERLAY")
            count:ClearAllPoints()
            count:SetFont(count:GetFont(), 10, "OUTLINE")
            count:SetPoint("TOPRIGHT", button, 0, 0)
        end
        
    end

    ---------------------------------------------------
    -- TARGET AURA SIZE
    ---------------------------------------------------
    
    hooksecurefunc("TargetFrame_UpdateAuraPositions", function(self, auraName, numAuras, numOppositeAuras, largeAuraList, updateFunc, maxRowWidth, offsetX, mirrorAurasVertically)
        local AURA_OFFSET_Y = 1
        local LARGE_AURA_SIZE = SCDB[module.name]["Large aura size"]
        local SMALL_AURA_SIZE = SCDB[module.name]["Small aura size"]
        local size
        local offsetY = AURA_OFFSET_Y
        local rowWidth = 0
        local firstBuffOnRow = 1
        
        for i=1, numAuras do
            if ( largeAuraList[i] ) then
                size = LARGE_AURA_SIZE
                offsetY = AURA_OFFSET_Y + AURA_OFFSET_Y
            else
                size = SMALL_AURA_SIZE
            end
            if ( i == 1 ) then
                rowWidth = size
                self.auraRows = self.auraRows + 1
            else
                rowWidth = rowWidth + size + offsetX
            end
            if ( rowWidth > maxRowWidth ) then
                updateFunc(self, auraName, i, numOppositeAuras, firstBuffOnRow, size, offsetX, offsetY, mirrorAurasVertically)

                rowWidth = size
                self.auraRows = self.auraRows + 1
                firstBuffOnRow = i
                offsetY = AURA_OFFSET_Y
            else
                updateFunc(self, auraName, i, numOppositeAuras, i - 1, size, offsetX, offsetY, mirrorAurasVertically)
            end
            setStyleAura(auraName, i, auraName:find("debuff"))
        end
    end)
    
    ---------------------------------------------------
    -- SEXY 3D PORTAITS
    ---------------------------------------------------
    function ChangePortaits(self)
        if self.portrait then
            if SCDB[module.name]["3D portaits"] == true then
                if not self.ap then
                    self.ap = _G[self.portrait:GetName().."Model"] or CreateFrame("PlayerModel", self.portrait:GetName().."Model", self.portrait:GetParent())
                    local guid = UnitGUID(self.unit)
                    if (not UnitExists(self.unit) or not UnitIsConnected(self.unit) or not UnitIsVisible(self.unit)) then
                        self.ap:SetModelScale(4.25)
                        self.ap:SetPosition(0, 0, -1.5)
                        self.ap:SetModel("Interface\\Buttons\\talktomequestionmark.mdx")
                    elseif(self.ap.guid ~= guid or (self.unit=="pet" and self.ap.guid == guid)) then
                        self.ap:SetUnit(self.unit)
                        self.ap:SetCamera(0)
                        self.ap.guid = guid
                    end
                    self.ap:SetSize(self.portrait:GetWidth()*.75, self.portrait:GetHeight()*.75)
                    self.ap:SetPoint("CENTER", self.portrait, "CENTER", 0, 0)
                    if self.unit ~= "player" then
                        self.ap:SetFrameLevel(self:GetFrameLevel()-1)
                    else
                        self.ap:SetFrameLevel(self:GetFrameLevel())
                    end
                    self.ap.back = self.ap:CreateTexture(nil, "BACKGROUND")
                    self.ap.back:SetTexture("Interface\\CharacterFrame\\TempPortraitAlphaMaskSmall")
                    self.ap.back:SetAllPoints(self.portrait)
                    self.ap.back:SetVertexColor(0,0,0)
                    self.ap.border = CreateFrame("frame", nil, self)
                    self.ap.border:SetAllPoints(self.portrait)
                    if self.unit ~= "player" then
                        self.ap.border:SetFrameLevel(self:GetFrameLevel())
                    else
                        self.ap.border:SetFrameLevel(self:GetFrameLevel()+1)
                    end
                    self.ap.border.tex = self.ap.border:CreateTexture(nil, "BORDER")
                    self.ap.border.tex:SetTexture("Interface\\CHARACTERFRAME\\TotemBorder")
                    self.ap.border.tex:SetSize(self.portrait:GetWidth()+16, self.portrait:GetWidth()+16)
                    self.ap.border.tex:SetPoint("CENTER")
                    self.ap.border.tex:SetVertexColor(0,0,0,.9)
                    
                    self:SetFrameStrata("LOW")
                    self.portrait:SetTexture("")
                else
                    self.portrait:SetTexture("")
                    self.ap:SetCamera(0)
                    local guid = UnitGUID(self.unit)
                    if (not UnitExists(self.unit) or not UnitIsConnected(self.unit) or not UnitIsVisible(self.unit)) then
                        self.ap:SetModelScale(4.25)
                        self.ap:SetPosition(0, 0, -1.5)
                        self.ap:SetModel("Interface\\Buttons\\talktomequestionmark.mdx")
                    elseif (self.ap.guid ~= guid  or (self.unit=="pet" or self.unit=="player" or self.unit:find("party"))) then
                        self.ap:SetUnit(self.unit)
                        self.ap:SetCamera(0)
                        self.ap.guid = guid
                    end
                end
            else
                if (not UnitExists(self.unit) or not UnitIsConnected(self.unit) or not UnitIsVisible(self.unit)) then
                    self.portrait:SetTexture("Interface\\CharacterFrame\\TempPortrait")
                    self.portrait:SetTexCoord(0,1,0,1)
                else
                    if SCDB[module.name]["Class portaits"] == true then
                        if (UnitIsPlayer(self.unit) and UnitExists(self.unit) and UnitIsConnected(self.unit) and self.unit~="pet") then
                            if select(2,UnitClass(self.unit)) == "DRUID" then
                                local i, flag=1, false
                                while UnitBuff(self.unit, i) do
                                    local id = select(11,UnitBuff(self.unit, i))
                                    --768 (Cat Form)  783(Travel Form) 1066 (Aquatic Form) 5487 (Bear Form) 24858 (Moonkin Form) 33891 (Tree of Life) 33943 (Flight Form) 40120 (Swift Flight Form)
                                    if id == 768 or id == 783 or id == 1066 or id == 5487 or id == 24858 or id == 33891 or id == 33943 or id == 40120 then
                                        SetPortraitToTexture(self.portrait, GetSpellTexture(id))
                                        self.portrait:SetTexCoord(0, 1, 0, 1)
                                        flag = true
                                    end
                                    i = i + 1
                                end
                                if not flag then
                                    self.portrait:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles")
                                    self.portrait:SetTexCoord(unpack(CLASS_ICON_TCOORDS.DRUID))
                                end
                            else
                                local t = CLASS_ICON_TCOORDS[select(2,UnitClass(self.unit))]
                                if t then
                                   self.portrait:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles")
                                   self.portrait:SetTexCoord(unpack(t))
                                end
                            end
                        else
                            self.portrait:SetTexCoord(0,1,0,1)
                        end
                    else
                        self.portrait:SetTexCoord(0,1,0,1)
                    end
                end
            end
        end
    end
    
    hooksecurefunc("UnitFramePortrait_Update", ChangePortaits)
    
    ---------------------------------------------------
    -- FIX TEXT VALUES FOR HP AND MANA BARS
    ---------------------------------------------------
    local function fixvalue(val)
       if(val >= 1e6) then
          return ('%.2fm'):format(val / 1e6):gsub('%.?0+([km])$', '%1')
       elseif(val >= 1e4) then
          return ('%.1fk'):format(val / 1e3):gsub('%.?0+([km])$', '%1')
       else
          return val
       end
    end

    hooksecurefunc("TextStatusBar_UpdateTextString", function(self)
        if self.TextString and self.currValue and not GetCVarBool("statusTextPercentage") then
            self.TextString:SetText(fixvalue(self.currValue))
        end
    end)

end
tinsert(SuperClassic.modules, module) -- finish him!